using System;
using GameStateManagement;
using Microsoft.Xna.Framework;

namespace Life
{
    // Clean up / General

    // TODO: error handling
    // TODO: global transition times
    // TODO: Sort out Life and GameStateManagement project boundaries
    // TODO: Save and Load panels are very similar.  Consolidate identicaly functionality
    // TODO: Gameplay buttons are hard-coded
    // TODO: Clean up Control event extensibility.  Too much copy paste!
    // TODO: Stop generations when cell count == 0, or when there are no more changes

    // Saves

    // TODO: consolidate hidden saved file extension.  too much scattered string building
    // TODO: Don't access isolated storage in application state management events
        // TODO: http://msdn.microsoft.com/en-us/library/ff817008(v=vs.92).aspx

    // UI
    
    // TODO: Save selection updates soo slowly
    // TODO: Confirm save overwrite

    // Animation
    
    // TODO: Better transitions
    // TODO: Button clicks

    // Art
    
    // TODO: Save, Load, Help look like a different them with their black backgrounds and white text
    // TODO: Make thumbnail background clear rather than black
    // TODO: Add a splash screen: http://msdn.microsoft.com/en-us/library/hh184840(v=vs.92).aspx

    // Features

    // TODO: Grid sizes
    // TODO: Handle both orietations
    // TODO: wrap board?
    // TODO: Save/load generation count
    // TODO: Feedback email button in About (bottom of Help screen)
    
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager _graphics;
        ScreenFactory _screenFactory;
        
        // Pass through to inherited non-static Game.Services
        // Expect there to only be one Game1 object
        private static GameServiceContainer _services = null;
        
        private GameManager _gameManager = null;
        private ScreenManager _screenManager = null;

        public Game1()
        {
            // Assuming a single instances of Game1
            _services = Services;

            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // Extend battery life under lock.
            InactiveSleepTime = TimeSpan.FromSeconds(1);

            _graphics.IsFullScreen = true;

            // Choose whether you want a landscape or portait game by using one of the two helper functions.
            //InitializeLandscapeGraphics();
            InitializePortraitGraphics();

            // Create the screen factory and add it to the Services
            _screenFactory = new ScreenFactory();
            Services.AddService(typeof(IScreenFactory), _screenFactory);

            // Create the screen manager component.
            _screenManager = new ScreenManager(this);
            Components.Add(_screenManager);

            // Add game manager service, which makes it easy to get a reference to the game manager from various screens
            _gameManager = new GameManager(this);
            Services.AddService(typeof(IGameManager), _gameManager);

            // Hook events on the PhoneApplicationService so we're notified of the application's life cycle
            Microsoft.Phone.Shell.PhoneApplicationService.Current.Launching +=
                new EventHandler<Microsoft.Phone.Shell.LaunchingEventArgs>(GameLaunching);
            Microsoft.Phone.Shell.PhoneApplicationService.Current.Activated +=
                new EventHandler<Microsoft.Phone.Shell.ActivatedEventArgs>(GameActivated);
            Microsoft.Phone.Shell.PhoneApplicationService.Current.Deactivated +=
                new EventHandler<Microsoft.Phone.Shell.DeactivatedEventArgs>(GameDeactivated);
            Microsoft.Phone.Shell.PhoneApplicationService.Current.Closing +=
                new EventHandler<Microsoft.Phone.Shell.ClosingEventArgs>(GameClosing);
        }

        public static object GetService(Type type)
        {
            if (_services == null)
                _services = new GameServiceContainer();

            return _services.GetService(type);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        private void AddInitialScreens()
        {
            LoadingScreen.Load(_screenManager, true, null, new BackgroundScreen(), new MainMenuScreen());
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        protected override void Draw(GameTime gameTime)
        {
            _graphics.GraphicsDevice.Clear(Color.Black);

            // The real drawing happens inside the screen manager component.
            base.Draw(gameTime);
        }

        /// <summary>
        /// Helper method to the initialize the game to be a portrait game.
        /// </summary>
        private void InitializePortraitGraphics()
        {
            _graphics.PreferredBackBufferWidth = 480;
            _graphics.PreferredBackBufferHeight = 800;
        }

        /// <summary>
        /// Helper method to initialize the game to be a landscape game.
        /// </summary>
        private void InitializeLandscapeGraphics()
        {
            _graphics.PreferredBackBufferWidth = 800;
            _graphics.PreferredBackBufferHeight = 480;
        }

        void GameLaunching(object sender, Microsoft.Phone.Shell.LaunchingEventArgs e)
        {
            AddInitialScreens();
        }

        void GameActivated(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
        {
            // Ensure game manager is initialized
            _gameManager.Initialize();

            // Try to deserialize the screen manager
            if (!_screenManager.Activate(e.IsApplicationInstancePreserved))
            {
                // If the screen manager fails to deserialize, add the initial screens
                AddInitialScreens();
            }
        }

        void GameDeactivated(object sender, Microsoft.Phone.Shell.DeactivatedEventArgs e)
        {
            // Serialize the screen manager when the game deactivated
            _screenManager.Deactivate();

            _gameManager.Deactivate();
        }

        void GameClosing(object sender, Microsoft.Phone.Shell.ClosingEventArgs e)
        {
            _gameManager.Deactivate();
        }
    }
}
